﻿const fs = require("fs");
const path = require("path");
const image = require("imageinfo"); //引用imageinfo模块
const tinify=require("tinify");

var open_path='';
var save_path='';
var compression_size=0;
var min_size=0.2;

function readFileList(path, filesList) {
        var files = fs.readdirSync(path);
        files.forEach(function (itm, index) {
            var stat = fs.statSync(path + itm);
            if (stat.isDirectory()) {
            //递归读取文件
                readFileList(path + itm + "/", filesList);
            } else {
                var obj = {};//定义一个对象存放文件的路径和名字
                obj.path = path;//路径
                obj.filename = itm;//名字
		obj.size=stat.size/1024/1024;
                filesList.push(obj);
            }

        });

    };
var getFiles = {
        //获取文件夹下的所有文件
        getFileList: function (path) {
            var filesList = [];
            readFileList(path, filesList);
            return filesList;
        },
        //获取文件夹下的所有图片
        getImageFiles:function (path) {
            var imageList=[];
            this.getFileList(path).forEach((item) => {
                var ms = image(fs.readFileSync(item.path + item.filename));
                let path=item.path;
                let s_path=path.substr(open_path.length,path.length);
                item.s_path=s_path;
                ms.mimeType&&(ms.mimeType=='image/png'||ms.mimeType=='image/jpeg') && (imageList.push(item))
            });
            return imageList;

        }
    };

function getStat(path){
    return new Promise((resolve, reject) => {
        fs.stat(path, (err, stats) => {
            if(err){
                resolve(false);
            }else{
                resolve(stats);
            }
        })
    })
};
function mkdir(dir) {
    return new Promise((resolve, reject) => {
        fs.mkdir(dir, err => {
            if (err) {
                resolve(false);
            } else {
                resolve(true);
            }
        })
    })
};
async function dirExists(dir) {
	if(!dir)return true;
    let isExists = await getStat(dir);
    //如果该路径且不是文件，返回true
    if (isExists && isExists.isDirectory()) {
        return true;
    } else if (isExists) {     //如果该路径存在但是文件，返回false
        return false;
    }
    //如果该路径不存在
    let tempDir = path.parse(dir).dir;      //拿到上级路径
    //递归判断，如果上级目录也不存在，则会代码会在此处继续循环执行，直到目录存在
    let status = await dirExists(tempDir);
    let mkdirStatus;
    if (status) {
        mkdirStatus = await mkdir(dir);
    }
    return mkdirStatus;
};

async function compression_img(callback){
    let isExists = await getStat(open_path);
    if(!isExists){
        console.warn('文件路径不存在:'+open_path);
        console.warn('请修改app.js 配置路径');
        return;
    }
    //获取文件夹下的所有图片
    var list=getFiles.getImageFiles(open_path);
    console.warn('获取('+open_path+')下的图片');
    console.warn('获取的图片张数:'+list.length);
    let com_count=0;
    let all_count=list.length;
    let ret_count=0;
    var fun=function(){
        while(list.length!=0){
            let img_obj=list.pop();
            if(img_obj&&(compression_size==0||img_obj.size>=compression_size)){
                com_count++;
                tinify_to_img(img_obj,(item)=>{
                    if(item&&item.size>=min_size&&item.com_count<=2){
                        console.warn('...........再次压缩...........');
                        console.warn(item);
                        all_count++;
                        list.push(item);
                        fun();
                    }
                    ret_count++;
                    if(ret_count===all_count){
                        console.warn('...........压缩图片,全部完成...........');
                    }
                });
            }
        }
    };
    fun();
    console.warn('需要压缩的图片张数:'+com_count);
};

async function tinify_to_img(item,callback){
    if(tinify.compressionCount>=500){
        console.warn('已经达到最大上限:'+tinify.compressionCount);
		if(callback)callback(null);
        return;
    }
    var _open=item.path+item.filename;
    var _save=save_path+item.s_path;
    if(item.com_count)item.com_count++;
    else item.com_count=1;

    let isExists = await getStat(_open);

    //如果该路径且不是文件，返回true
    if(!isExists){
        console.warn('路径不存在:'+_open);
		if(callback)callback(null);
        return;
    }
    await dirExists(_save);
    console.log('开始压缩>>>>>>>'+item.filename);
    fs.readFile(_open, function(err, sourceData) {
        if(err){
            if(callback)callback(null);
            throw err;
        }
        tinify.fromBuffer(sourceData).toBuffer(function(err, resultData) {
            if(err){
                if(callback)callback(null);
                console.warn(err);
                throw err;
            }
            fs.writeFile(_save+item.filename,resultData, function(err) {
                if(err){
                    if(callback)callback(null);
                    console.warn(err);
                }
                else{
                    console.log('压缩完成>>>>>>>'+item.filename);
                    console.log('保存路径>>>>>>>'+_save);
                    console.log('压缩上限:'+tinify.compressionCount+'/500');
                    if(callback)callback(item);
                }
            });
        });
    });
};

exports.start = function(openpath,savepath,key,_size){
    //console.log(openpath,savepath,key)
    tinify.key=key;
    open_path=openpath;
    save_path=savepath;
    compression_size=_size;
    compression_img();
};
